﻿using PlutoStudio.Net.Messages;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlutoStudio.Net.Processors
{
    public interface IFilter
    {
        bool AllowMultiple { get; }

        int Order { get; }
    }

    public interface IAuthorizationFilter : IFilter
    {
        bool OnAuthorization(MessageProcessorBase process);
    }

    public interface IExceptionFilter : IFilter
    {
        // Methods
        void OnException(MessageProcessorBase process, Exception ex);
    }

    public interface IDecryptionFilter : IFilter
    {
        void OnDecryptValue(MessageProcessorBase process);
    }

    public interface IEncryptionFilter : IFilter
    {
        Message OnEncryptValue(MessageProcessorBase process, Message message);
    }


    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public abstract class FilterAttribute : Attribute, IFilter
    {
        private static readonly ConcurrentDictionary<Type, bool> _multiuseAttributeCache = new ConcurrentDictionary<Type, bool>();
        private int _order = -1;

        // Methods
        protected FilterAttribute()
        {
        }

        private static bool AllowsMultiple(Type attributeType)
        {
            return _multiuseAttributeCache.GetOrAdd(attributeType, type => type.GetCustomAttributes(typeof(AttributeUsageAttribute), true).Cast<AttributeUsageAttribute>().First<AttributeUsageAttribute>().AllowMultiple);
        }

        // Properties
        public bool AllowMultiple
        {
            get
            {
                return AllowsMultiple(base.GetType());
            }
        }

        public int Order
        {
            get
            {
                return this._order;
            }
            set
            {
                if (value < -1)
                {
                    throw new ArgumentOutOfRangeException("value", "Order值不能小于0！");
                }
                this._order = value;
            }
        }

    }

    public class AuthorizationAttribute : FilterAttribute, IAuthorizationFilter
    {

        bool IAuthorizationFilter.OnAuthorization(MessageProcessorBase process)
        {
            if (!process.Context.User.Identity.IsAuthenticated)
            {
                var message = new Message(process.Message.Flag, process.Message.Code, (UInt16)StatusCode.Unauthorized);
                message.SetData("操作被拒绝，身份验证失败！");
                process.Context.Send(message);
                return false;
            }
            return true;
        }
    }

    public class HandlerErrorAttribute : FilterAttribute, IExceptionFilter
    {
        public void OnException(MessageProcessorBase process, Exception ex)
        {
            var message = new Message(process.Message.Flag, process.Message.Code, (ushort)StatusCode.InternalServerError);
            var error = ex.InnerException ?? ex;
            message.SetData(error.Message);
            process.Context.Send(message);
        }
    }

    public abstract class DecryptionAttribute : FilterAttribute, IDecryptionFilter
    {
        public void OnDecryptValue(MessageProcessorBase process)
        {
            process.Message.SetData(DecryptData(process.Context, process.Message.Data));
        }

        public abstract byte[] DecryptData(NetContext context, byte[] data);
    }

    public abstract class EncryptionAttribute : FilterAttribute, IEncryptionFilter
    {
        public Message OnEncryptValue(MessageProcessorBase process, Message message)
        {
            message.SetData(EncryptData(process.Context, message.Data));
            return message;
        }

        public abstract byte[] EncryptData(NetContext context, byte[] data);

    }

}
